#!./perl

BEGIN {
  $| = 1;
}

use Math::GMP;
use Test;
use strict;

my ($f,$try,$x,$y,$ans,@tests,@data,@args,$ans1,$z,$line);

@data = <DATA>;
@tests = grep { ! /^&/ } @data;
plan tests => (scalar @tests
  + 2);				# one extra
close DATA;

while (defined($line = shift @data)) {
  chomp $line;
  if ($line =~ s/^&//) {
    $f = $line; next;
  }
  @args = split(/:/,$line,99);
  $ans = pop(@args);

  if ( $args[0] =~ /^i([-+]?\d+)$/ ) {
    $try = "\$x = $1;";
  } elsif ( $args[0] =~ /^b([-+]?.+),([0-9]+)$/ ) {
    $try = "\$x = new Math::GMP \"$1\", $2;";
  } else {
    $try = "\$x = new Math::GMP \"$args[0]\";";
  }

  if ($f eq "bnorm") {
    $try .= "\$x+0;";
  } elsif ($f eq "fibonacci") {
    $try .= 'Math::GMP::fibonacci($x);';
  } elsif ($f eq "bfac") {
    $try .= '$x->bfac();';
  } elsif ($f eq "bneg") {
    $try .= "-\$x;";
  } elsif ($f eq "babs") {
    $try .= "abs \$x;";
  } elsif ($f eq "square_root") {
    $try .= 'Math::GMP::gmp_sqrt($x);';
  } elsif ($f eq 'uintify') {
    $try .= "Math::GMP::uintify_gmp(\$x);";
  } elsif ($f eq 'intify') {
    $try .= "Math::GMP::intify_gmp(\$x);";
  } elsif ($f eq 'new_from_base') {
    $try .= "\$x;";
  } else {
    if ( $args[1] =~ /^i([-+]?\d+)$/ ) {
      $try .= "\$y = $1;";
    }
    else {
      $try .= "\$y = new Math::GMP \"$args[1]\";";
    }
    if ($f eq 'bcmp') {
      $try .= "\$x <=> \$y;";
    } elsif ($f eq 'band') {
      $try .= "\$x & \$y;";
    } elsif ($f eq 'bxor') {
	$try .= "\$x ^ \$y;";
    } elsif ($f eq 'bior') {
	$try .= "\$x | \$y;";
    } elsif ($f eq 'badd') {
	$try .= "\$x + \$y;";
    } elsif ($f eq 'bsub') {
	$try .= "\$x - \$y;";
    } elsif ($f eq 'bmul') {
	$try .= "\$x * \$y;";
    } elsif ($f eq 'bdiv') {
	$try .= "\$x / \$y;";
    } elsif ($f eq 'bmod') {
	$try .= "\$x % \$y;";
    } elsif ($f eq 'bdiv2a') {
	$try .= "((Math::GMP::bdiv(\$x, \$y))[0]);";
    } elsif ($f eq 'bdiv2b') {
	$try .= "((Math::GMP::bdiv(\$x, \$y))[1]);";
    } elsif ($f eq 'bgcd') {
      $try .= "Math::GMP::bgcd(\$x, \$y);";
    } elsif ($f eq 'gcd') {
	$try .= "Math::GMP::gcd(\$x, \$y);";
    } elsif ($f eq 'sizeinbase') {
        $try .= "Math::GMP::sizeinbase_gmp(\$x, \$y);";
    } elsif ($f eq 'add_ui') {
        $try .= "Math::GMP::add_ui_gmp(\$x, \$y); \$x";
    } elsif ($f eq 'mul_2exp') {
        $try .= "Math::GMP::mul_2exp_gmp(\$x, \$y);";
    } elsif ($f eq 'div_2exp') {
        $try .= "Math::GMP::div_2exp_gmp(\$x, \$y);";
    } elsif ($f eq 'mmod') {
       $try .= "Math::GMP::mmod_gmp(\$x, \$y);";
    } elsif ($f eq 'mod_2exp') {
       $try .= "Math::GMP::mod_2exp_gmp(\$x, \$y);";
    } elsif ($f eq 'legendre') {
       $try .= "Math::GMP::legendre(\$x, \$y);";
    } elsif ($f eq 'jacobi') {
       $try .= "Math::GMP::jacobi(\$x, \$y);";
    } elsif ($f eq 'test_bit') {
       $try .= "Math::GMP::gmp_tstbit(\$x, \$y);";
    } else {
      if ( $args[2] =~ /^i([-+]?\d+)$/ ) {
	  $try .= "\$z = $1;";
      } else {
	  $try .= "\$z = new Math::GMP \"$args[2]\";";
      }
	if ($f eq 'powm') {
          $try .= "Math::GMP::powm_gmp(\$x, \$y, \$z);";
      } else {
	  warn "Unknown op";
      }
    }
  }
  $ans1 = eval $try;
  print "# Tried '$try'\n" if !ok("$ans1",$ans); # need "$ans1" due to bug

}

# some assorted tests for internal functions

$x = Math::GMP->new('123'); $y = Math::GMP::gmp_copy($x);
ok (ref($y),ref($x)); ok ("$y",'123');
# doing ok ($y,'123'); (no ""!) will crash. This looks like a nasty bug...

# all done
 
__END__
&bcmp
+0:0:0
-1:0:-1
+0:-1:1
+1:0:1
+0:1:-1
-1:1:-1
+1:-1:1
-1:-1:0
+1:1:0
+123:123:0
+123:12:1
+12:123:-1
-123:-123:0
-123:-12:-1
-12:-123:1
+123:124:-1
+124:123:1
-123:-124:1
-124:-123:-1
+100:5:1
i+100:5:1
+100:i5:1
i-10:-10:0
&badd
+0:0:0
+1:0:1
+0:1:1
+1:1:2
-1:0:-1
+0:-1:-1
-1:-1:-2
-1:1:0
+1:-1:0
+9:1:10
+99:1:100
+999:1:1000
+9999:1:10000
+99999:1:100000
+999999:1:1000000
+9999999:1:10000000
i+9999999:1:10000000
+99999999:1:100000000
+999999999:1:1000000000
+9999999999:1:10000000000
+99999999999:1:100000000000
+99999999999:i1:100000000000
+10:-1:9
+100:-1:99
+1000:-1:999
+10000:-1:9999
+100000:-1:99999
+1000000:-1:999999
+10000000:-1:9999999
+100000000:-1:99999999
+1000000000:-1:999999999
+10000000000:-1:9999999999
+123456789:987654321:1111111110
-123456789:987654321:864197532
-123456789:-987654321:-1111111110
+123456789:-987654321:-864197532
&bsub
+0:0:0
+1:0:1
+0:1:-1
+1:1:0
-1:0:-1
+0:-1:1
-1:-1:0
-1:1:-2
+1:-1:2
+9:1:8
+99:1:98
+999:1:998
+9999:1:9998
+99999:1:99998
+999999:1:999998
+9999999:1:9999998
+99999999:1:99999998
+999999999:1:999999998
+9999999999:1:9999999998
+99999999999:1:99999999998
+99999999999:i1:99999999998
+10:-1:11
+100:-1:101
+1000:-1:1001
+10000:-1:10001
+100000:-1:100001
+1000000:-1:1000001
+10000000:-1:10000001
+100000000:-1:100000001
+1000000000:-1:1000000001
+10000000000:-1:10000000001
+123456789:987654321:-864197532
-123456789:987654321:-1111111110
-123456789:-987654321:864197532
+123456789:-987654321:1111111110
i4:12345678987:-12345678983
&bmul
+0:0:0
+0:1:0
+1:0:0
+0:-1:0
-1:0:0
+123456789123456789:0:0
+0:123456789123456789:0
-1:-1:1
-1:1:-1
+1:-1:-1
+1:1:1
+2:3:6
-2:3:-6
+2:-3:-6
-2:-3:6
+111:111:12321
+10101:10101:102030201
+1001001:1001001:1002003002001
+100010001:100010001:10002000300020001
+10000100001:10000100001:100002000030000200001
+11111111111:9:99999999999
+11111111111:i9:99999999999
i9:+11111111111:99999999999
+22222222222:9:199999999998
+33333333333:9:299999999997
+44444444444:9:399999999996
+55555555555:9:499999999995
+66666666666:9:599999999994
+77777777777:9:699999999993
+88888888888:9:799999999992
+99999999999:9:899999999991
&bdiv2a
+0:1:0
+0:-1:0
+1:1:1
-1:-1:1
+1:-1:-1
-1:1:-1
+1:2:0
+2:1:2
+1000000000:9:111111111
+1000000000:i9:111111111
+2000000000:9:222222222
+3000000000:9:333333333
+4000000000:9:444444444
+5000000000:9:555555555
+6000000000:9:666666666
+7000000000:9:777777777
+8000000000:9:888888888
+9000000000:9:1000000000
+35500000:113:314159
+71000000:226:314159
+106500000:339:314159
+1000000000:3:333333333
+10:5:2
+100:4:25
+1000:8:125
+10000:16:625
i+10000:16:625
+999999999999:9:111111111111
+999999999999:99:10101010101
+999999999999:999:1001001001
+999999999999:9999:100010001
+999999999999999:99999:10000100001
&bdiv
+0:1:0
+0:-1:0
+1:1:1
-1:-1:1
+1:-1:-1
-1:1:-1
+1:2:0
+2:1:2
+1000000000:9:111111111
+1000000000:i9:111111111
+2000000000:9:222222222
+3000000000:9:333333333
+4000000000:9:444444444
+5000000000:9:555555555
+6000000000:9:666666666
+7000000000:9:777777777
+8000000000:9:888888888
+9000000000:9:1000000000
+35500000:113:314159
+71000000:226:314159
+106500000:339:314159
+1000000000:3:333333333
+10:5:2
+100:4:25
+1000:8:125
+10000:16:625
i+10000:16:625
+999999999999:9:111111111111
+999999999999:99:10101010101
+999999999999:999:1001001001
+999999999999:9999:100010001
+999999999999999:99999:10000100001
&bdiv2b
+0:1:0
+0:-1:0
+1:1:0
-1:-1:0
+1:-1:0
-1:1:0
+1:2:1
+2:1:0
+1000000000:9:1
+1000000000:i9:1
+2000000000:9:2
+3000000000:9:3
+4000000000:9:4
+5000000000:9:5
+6000000000:9:6
+7000000000:9:7
+8000000000:9:8
+9000000000:9:0
+35500000:113:33
i+35500000:113:33
+71000000:226:66
+106500000:339:99
+1000000000:3:1
+10:5:0
+100:4:0
+1000:8:0
+10000:16:0
+999999999999:9:0
+999999999999:99:0
+999999999999:999:0
+999999999999:9999:0
+999999999999999:99999:0
&bmod
+0:1:0
+0:-1:0
+1:1:0
-1:-1:0
+1:-1:0
-1:1:0
+1:2:1
+2:1:0
+1000000000:9:1
+1000000000:i9:1
+2000000000:9:2
+3000000000:9:3
+4000000000:9:4
+5000000000:9:5
+6000000000:9:6
+7000000000:9:7
+8000000000:9:8
+9000000000:9:0
+35500000:113:33
i+35500000:113:33
+71000000:226:66
+106500000:339:99
+1000000000:3:1
+10:5:0
+100:4:0
+1000:8:0
+10000:16:0
+999999999999:9:0
+999999999999:99:0
+999999999999:999:0
+999999999999:9999:0
+999999999999999:99999:0
&bgcd
+0:0:0
+0:1:1
+1:0:1
+1:1:1
+2:3:1
+3:2:1
+100:625:25
+4096:81:1
&gcd
+0:0:0
+0:1:1
+1:0:1
+1:1:1
+2:3:1
+3:2:1
+100:625:25
+4096:81:1
&new_from_base
0xff:255
0x2395fa:2332154
babcdefgh,36:808334348993
&sizeinbase
+5:i10:1
+9999999999:i16:9
-5000:i2:13
&uintify
+15:15
+9999999999:1410065407
+99999999999:1215752191
+999999999999:3567587327
&add_ui
+999999:i1:1000000
+9999999:i1:10000000
+99999999:i1:100000000
&intify
+999999999:999999999
+9999999999:1410065407
&mul_2exp
+9999:i9:5119488
+99999:i9:51199488
+0:i1:0
+1:i0:1
&div_2exp
+999999:i1111:0
+0:i1:0
&powm
+99999:999999:99:27
+1:1:1:0
+1:0:1:0
&mmod
+99999:100002:99999
+1:1:0
&mod_2exp
+99999999:11111:99999999
+0:1:0
&jacobi
+1:15:1
+1:15:1
+2:15:1
+3:15:0
+4:15:1
+5:15:0
+6:15:0
+7:15:-1
+8:15:1
+9:15:0
+10:15:0
+11:15:-1
+12:15:0
+13:15:-1
+14:15:-1
+15:15:0
&band
7:3:3
2:3:2
4:1:0
&bxor
7:3:4
2:3:1
4:1:5
&bior
7:3:7
2:3:3
4:1:5
&bfac
1:1
2:2
3:6
4:24
5:120
6:720
&fibonacci
2:1
3:2
4:3
5:5
6:8
7:13
8:21
9:34
10:55
&test_bit
10:0:0
1:0:1
3:1:1
3:2:0
&square_root
16:4
1:1
0:0
100:10
101:10
99:9
